<template>
  <div class="indicator-topology-container">
    <div class="topology-title">指标体系拓扑图</div>
    <div ref="topologyRef" class="topology-content" />
    <el-button class="back-button" @click="handleBack">返回</el-button>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, defineProps, defineEmits, onUnmounted, watch } from "vue";
import LogicFlow from "@logicflow/core";
import "@logicflow/core/lib/style/index.css";
import { ElMessage, ElLoading } from "element-plus";
import {
  CircleNode,
  CircleNodeModel,
  RectNode,
  RectNodeModel,
  PolylineEdge,
  PolylineEdgeModel,
  h,
  BaseEdge,
} from "@logicflow/core";
// 尝试从主模块导入EdgeModel
// 导入BaseEdgeModel替代EdgeModel
import { BaseEdgeModel } from "@logicflow/core";
import IndicatorAPI, {
  IndicatorTopologyResponse,
  IndicatorListParameter,
} from "@/api/indicationManage/indexNew";

// 定义 props
const props = defineProps<{
  topologyId: string | number | null;
}>();

// 定义 emits
const emit = defineEmits(["back"]);

const topologyRef = ref<HTMLDivElement | null>(null);
let lf: LogicFlow | null = null;
const indicatorData = ref<IndicatorTopologyResponse>({});
const loading = ref(false);

// 处理返回事件
const handleBack = () => {
  emit("back");
};

// 获取拓扑图数据
const fetchTopologyData = async (id: string | number) => {
  loading.value = true;
  try {
    const params: IndicatorListParameter = { id };
    const data = await IndicatorAPI.Topology(params);
    indicatorData.value = data;
    return data;
  } catch (error) {
    ElMessage.error("获取拓扑图数据失败");
    console.error("获取拓扑图数据失败:", error);
    return null;
  } finally {
    loading.value = false;
  }
};

// 注册自定义节点
const registerCustomNodes = (lf: LogicFlow) => {
  // 关键指标节点
  class KeyIndicatorNode extends CircleNode {
    getShape() {
      const { x, y } = this.props.model;
      const style = this.props.model.getNodeStyle();
      return h("g", {}, [
        h("circle", {
          ...style,
          cx: x,
          cy: y,
          r: 40,
          fill: "#1a56db", // 深蓝色
        }),
      ]);
    }
    getText() {
      const { x, y, text } = this.props.model;
      return h(
        "text",
        {
          x: x,
          y: y,
          fill: "#000",
          textAnchor: "middle",
          alignmentBaseline: "middle",
          style: { fontSize: 14, fontWeight: "bold" },
        },
        text.value
      );
    }
  }

  class KeyIndicatorNodeModel extends CircleNodeModel {
    setAttributes() {
      this.text = { value: this.properties.name || "关键指标" };
      this.r = 40;
    }
  }

  // 一级指标节点
  class Level1IndicatorNode extends RectNode {
    getShape() {
      const { x, y, width, height } = this.props.model;
      const style = this.props.model.getNodeStyle();
      return h("g", {}, [
        h("rect", {
          ...style,
          x: x - width / 2,
          y: y - height / 2,
          width,
          height,
          rx: 6,
          ry: 6,
          fill: "#3b82f6", // 淡蓝色
        }),
      ]);
    }
    getText() {
      const { x, y, text } = this.props.model;
      return h(
        "text",
        {
          x: x,
          y: y,
          fill: "#000",
          textAnchor: "middle",
          alignmentBaseline: "middle",
          style: { fontSize: 14, fontWeight: "bold" },
        },
        text.value
      );
    }
  }

  class Level1IndicatorNodeModel extends RectNodeModel {
    setAttributes() {
      this.text = { value: this.properties.name || "一级指标" };
      this.width = 120;
      this.height = 60;
    }
  }

  // 二级指标节点模型
  class Level2IndicatorNodeModel extends RectNodeModel {
    setAttributes() {
      this.text = { value: this.properties.name || "二级指标" };
      this.width = 100;
      this.height = 40;
    }
  }

  // 二级指标节点组件
  class Level2IndicatorNode extends RectNode {
    getShape() {
      const { x, y, width, height } = this.props.model;
      const style = this.props.model.getNodeStyle();
      return h("g", {}, [
        h("rect", {
          ...style,
          x: x - width / 2,
          y: y - height / 2,
          width,
          height,
          rx: 6,
          ry: 6,
          fill: "#93c5fd", // 浅蓝色
        }),
      ]);
    }
    getText() {
      const { x, y, text } = this.props.model;
      return h(
        "text",
        {
          x: x,
          y: y,
          fill: "#000",
          textAnchor: "middle",
          alignmentBaseline: "middle",
          style: { fontSize: 12 },
        },
        text.value
      );
    }
  }

  // 边
  class PolylineEdgeModel extends BaseEdgeModel {
    setAttributes() {
      this.isAnimation = true;
    }
    getEdgeStyle() {
      const style = super.getEdgeStyle();
      style.stroke = "#888";
      style.strokeWidth = 1.5;
      style.strokeDasharray = "5 5";
      return style;
    }
  }

  class PolylineEdge extends BaseEdge {
    getShape() {
      const { model } = this.props;
      const { startPoint, endPoint } = model;
      const style = model.getEdgeStyle();
      return h("path", {
        ...style,
        d: `M ${startPoint.x} ${startPoint.y} L ${endPoint.x} ${endPoint.y}`,
        fill: "none",
      });
    }
  }

  // 注册节点
  lf.register({ type: "key-indicator", view: KeyIndicatorNode, model: KeyIndicatorNodeModel });
  lf.register({
    type: "level1-indicator",
    view: Level1IndicatorNode,
    model: Level1IndicatorNodeModel,
  });
  lf.register({
    type: "level2-indicator",
    view: Level2IndicatorNode,
    model: Level2IndicatorNodeModel,
  });

  // 注册边
  lf.register({
    type: "polyline-edge",
    view: PolylineEdge,
    model: PolylineEdgeModel,
  });
};

// 构建拓扑图数据
const buildTopologyData = (data: any): { nodes: any[]; edges: any[] } => {
  const nodes: any[] = [];
  const edges: any[] = [];
  const positions = new Map();
  const existingNodeIds = new Set(); // 用于跟踪已处理过的节点ID

  // 确保 data 是一个数组
  let dataArray = Array.isArray(data) ? data : [data];

  // 设置顶级节点数量
  const topLevelCount = dataArray.length;

  // 保持所有顶级节点在同一层级，不修改原始名称
  dataArray = dataArray.map((node) => {
    return { ...node };
  });

  // 计算节点位置的辅助函数 - 层级树状布局
  const calculatePosition = (
    node: any,
    parentId: number | null = null,
    level: number = 0,
    index: number = 0,
    total: number = 1
  ) => {
    // 层级间距和水平间距
    const verticalSpacing = 120;
    const horizontalSpacing = 180;

    // 顶级节点水平排列
    if (parentId === null) {
      // 计算顶级节点总宽度
      const totalWidth = (total - 1) * horizontalSpacing;
      // 起始位置（居中对齐）
      const startX = 400 - totalWidth / 2;
      return {
        x: startX + index * horizontalSpacing,
        y: 100,
      };
    }

    // 获取父节点位置
    const parentPosition = positions.get(parentId) || { x: 400, y: 100 };

    // 对于一级节点，水平排列在顶级节点下方
    if (level === 1) {
      // 计算总宽度
      const totalWidth = (total - 1) * horizontalSpacing;
      // 计算起始X坐标
      const startX = parentPosition.x - totalWidth / 2;
      return {
        x: startX + index * horizontalSpacing,
        y: parentPosition.y + verticalSpacing,
      };
    }

    // 对于二级及以下节点，水平排列在父节点下方
    return {
      x: parentPosition.x + (index - (total - 1) / 2) * horizontalSpacing,
      y: parentPosition.y + verticalSpacing,
    };
  };

  // 递归构建节点和边
  const traverse = (
    node: any,
    parentId: number | null = null,
    level: number = 0,
    index: number = 0,
    total: number = 1
  ) => {
    // 确定节点类型
    let nodeType = "level2-indicator";
    if (parentId === null) {
      // 顶级节点 (pid 为 null)
      nodeType = "key-indicator";
      // 顶级节点名称已在前面处理
    } else if (!node.children || node.children.length === 0) {
      nodeType = "level2-indicator";
    } else {
      nodeType = "level1-indicator";
      // 使用原始名称，不做修改
    }

    // 计算位置
    const position = calculatePosition(node, parentId, level, index, total);
    positions.set(node.id, position);

    // 检查节点ID是否已存在
    const nodeId = node.id.toString();
    if (!existingNodeIds.has(nodeId)) {
      // 添加节点
      nodes.push({
        id: nodeId,
        type: nodeType,
        x: position.x,
        y: position.y,
        properties: {
          name: node.name,
        },
      });
      existingNodeIds.add(nodeId);
    }

    // 添加边
    if (parentId !== null) {
      edges.push({
        type: "polyline-edge",
        sourceNodeId: parentId.toString(),
        targetNodeId: nodeId,
        properties: {
          isActived: true,
        },
      });
    }

    // 递归处理子节点
    if (node.children && node.children.length > 0) {
      node.children.forEach((child: any, idx: number) => {
        traverse(child, node.id, level + 1, idx, node.children.length);
      });
    }
  };

  // 遍历数组中的所有顶级节点
  dataArray.forEach((node, index) => {
    traverse(node, null, 0, index, dataArray.length);
  });

  return { nodes, edges };
};

// 初始化拓扑图
const initTopology = async () => {
  if (!topologyRef.value || !props.topologyId) return;

  // 显示加载中
  const loadingInstance = ElLoading.service({
    target: topologyRef.value,
    text: "加载中...",
  });

  try {
    // 销毁已有实例
    if (lf) {
      lf.destroy();
    }

    // 获取数据
    const data = await fetchTopologyData(props.topologyId);
    if (!data) return;

    // 创建新实例
    lf = new LogicFlow({
      container: topologyRef.value,
      grid: true,
      plugins: [],
      background: {
        color: "#f5f7fa",
      },
      nodeText: {
        fontSize: 14,
      },
      // 禁止拖拽
      stopMoveGraph: false,
      stopZoomGraph: false,
    });

    // 注册自定义节点
    registerCustomNodes(lf);

    // 构建数据
    const { nodes, edges } = buildTopologyData(data);

    // 设置数据
    lf.render({
      nodes,
      edges,
    });

    // 居中显示
    lf.translateCenter();

    // 监听窗口大小变化
    window.addEventListener("resize", () => {
      lf?.resize();
    });
  } catch (error) {
    ElMessage.error("初始化拓扑图失败");
    console.error("初始化拓扑图失败:", error);
  } finally {
    // 关闭加载中
    loadingInstance.close();
  }
};

// 监听topologyId变化，重新初始化拓扑图
watch(
  () => props.topologyId,
  (newId) => {
    if (newId) {
      initTopology();
    }
  },
  {
    immediate: true,
  }
);

// 组件挂载时初始化
onMounted(() => {
  if (props.topologyId) {
    initTopology();
  } else {
    ElMessage.error("没有指定拓扑图ID");
  }
});

// 组件卸载时清理
onUnmounted(() => {
  if (lf) {
    lf.destroy();
    lf = null;
  }
  window.removeEventListener("resize", () => {});
});
</script>

<style scoped>
.indicator-topology-container {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  padding: 20px;
}

.topology-title {
  margin-bottom: 20px;
  font-size: 24px;
  font-weight: bold;
  color: #333;
  text-align: center;
}

.topology-content {
  flex: 1;
  width: 100%;
  min-height: calc(100vh - 120px);
  overflow: auto;
  background-color: #f5f7fa;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.back-button {
  align-self: center;
  margin-top: 20px;
  margin-bottom: 20px;
}
</style>
